package main

import (
	"encoding/json"
	"fmt"
)

var jsonString17 string = `{
        "things": [
            {
                "name": "Alice",
                "age": 37
            },
            {
                "city": "Ipoh",
                "country": "Malaysia"
            },
            {
                "name": "Bob",
                "age": 36
            },
            {
                "city": "Northampton",
                "country": "England"
            }
        ]
    }`

type Mixed17 struct {
	Name    string `json:"name"`
	Age     int    `json:"age"`
	city    string `json:"city"`
	Country string `json:"country"`
}

type Person17 struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

type Place17 struct {
	City    string `json:"city"`
	Country string `json:"country"`
}

//func decode17(jsonStr []byte) (persons []Person17, places []Place17) {
//	var data map[string][]Mixed17
//	err := json.Unmarshal(jsonStr, &data)
//	if err != nil {
//		fmt.Println(err)
//		return
//	}
//	fmt.Printf("%+v\n", data["things"])
//	for i := range data["things"] {
//		item := data["things"][i]
//		if item.Name != "" {
//			persons = append(persons, Person17{Name: item.Name, Age: item.Age})
//		} else {
//			places = append(places, Place17{City: item.city, Country: item.Country})
//		}
//	}
//	return
//}

func addPerson17(item json.RawMessage, persons []Person17) []Person17 {
	person := Person17{}
	if err := json.Unmarshal(item, &person); err != nil {
		fmt.Println(err)
	} else {
		if person != *new(Person17) {
			persons = append(persons, person)
		}
	}
	return persons
}

func addPlace17(item json.RawMessage, places []Place17) []Place17 {
	place := Place17{}
	if err := json.Unmarshal(item, &place); err != nil {
		fmt.Println(err)
	} else {
		if place != *new(Place17) {
			places = append(places, place)
		}
	}
	return places
}

func decode17(jsonStr []byte) (persons []Person17, places []Place17) {
	var data map[string][]json.RawMessage
	err := json.Unmarshal(jsonStr, &data)
	if err != nil {
		fmt.Println(err)
		return
	}

	for _, item := range data["things"] {
		persons = addPerson17(item, persons)
		places = addPlace17(item, places)
	}
	return
}

func main() {
	personsA, placesA := decode17([]byte(jsonString17))
	fmt.Printf("%+v\n", personsA)
	fmt.Printf("%+v\n", placesA)
}
